﻿using System;
using System.Security.AccessControl;
using Company.Common;
using Company.Common.Helper;
using Company.IO.Interfaces;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Company.System.IO.IntegrationTests
{
    public partial class DirectoryTest : TestBase<IDirectory>
    {
        private const string _SGetAccessControlMethodName = "GetAccessControl";

        [TestMethod]
        public void GetAccessControl_PathValid_DirectorySecurity()
        {
            //Arrange
            string path = SLocalPath;
            DirectorySecurity expected = global::System.IO.Directory.GetAccessControl(path);

            //Act
            DirectorySecurity actual = Directory.GetAccessControl(path);

            //Assert
            CompareDirectorySecurity(expected, actual);
        }

        [TestMethod]
        [Ignore]
        public void GetAccessControl_PathValid_AccessControlSectionsAll_DirectorySecurity()
        {
            //Arrange
            const string path = ".\\";
            const AccessControlSections includeSections = AccessControlSections.All;
            DirectorySecurity expected = global::System.IO.Directory.GetAccessControl(path, includeSections);

            //Act
            DirectorySecurity actual = Directory.GetAccessControl(path, includeSections);

            //Assert
            CompareDirectorySecurity(expected, actual);
        }

        [TestMethod]
        public void GetAccessControl_PathNull_ArgumentNullException()
        {
            PathNull_ArgumentNullException(_SGetAccessControlMethodName);
        }

        [TestMethod]
        public void GetAccessControl_PathNull_AccessControlSectionsAll_ArgumentNullException()
        {
            //Arrange
            Type[] parameterTypes = GetTypeArray<string, AccessControlSections>();
            object[] parameterValues = GetValueArray(SStringNull, AccessControlSections.All);
            //Act
            ExpectException<ArgumentNullException>(_SGetAccessControlMethodName, parameterTypes, parameterValues);
            //Assert
        }

        [TestMethod]
        public void GetAccessControl_PathEmpty_ArgumentException()
        {
            PathEmpty_ArgumentException(_SGetAccessControlMethodName);
        }

        [TestMethod]
        public void GetAccessControl_PathEmpty_AccessControlSectionsAll_ArgumentException()
        {
            //Arrange
            Type[] parameterTypes = GetTypeArray<string, AccessControlSections>();
            object[] parameterValues = GetValueArray(string.Empty, AccessControlSections.All);
            //Act
            ExpectException<ArgumentException>(_SGetAccessControlMethodName, parameterTypes, parameterValues);
            //Assert
        }

        [TestMethod]
        public void GetAccessControl_PathNotExists_AccessControlSectionsAll_SystemException()
        {
            //Arrange
            Type[] parameterTypes = GetTypeArray<string, AccessControlSections>();
            object[] parameterValues = GetValueArray(".\\NotExists\\", AccessControlSections.All);
            //Act
            ExpectException<SystemException>(_SGetAccessControlMethodName, parameterTypes, parameterValues);
            //Assert
        }

        private static void CompareDirectorySecurity(DirectorySecurity expected, DirectorySecurity actual)
        {
            CompanyContract.ThrowIfNull(expected, "expected is null.");
            CompanyContract.ThrowIfNull(actual, "actual is null.");

            Assert.AreEqual(expected.AccessRightType, actual.AccessRightType);
            Assert.AreEqual(expected.AccessRuleType, actual.AccessRuleType);
            Assert.AreEqual(expected.AreAccessRulesCanonical, actual.AreAccessRulesCanonical);
            Assert.AreEqual(expected.AreAccessRulesProtected, actual.AreAccessRulesProtected);
            Assert.AreEqual(expected.AreAuditRulesCanonical, actual.AreAuditRulesCanonical);
            Assert.AreEqual(expected.AreAuditRulesProtected, actual.AreAuditRulesProtected);
            Assert.AreEqual(expected.AuditRuleType, actual.AuditRuleType);
        }
    }
}